home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * FREXX PROGRAMMING LANGUAGE *
- ******************************************************************************
-
- statement.c
-
- Support routines to the Expression() function.
-
- *****************************************************************************/
-
- /************************************************************************
- * *
- * fpl.library - A shared library interpreting script langauge. *
- * Copyright (C) 1992-1994 FrexxWare *
- * Author: Daniel Stenberg *
- * *
- * This program is free software; you may redistribute for non *
- * commercial purposes only. Commercial programs must have a written *
- * permission from the author to use FPL. FPL is *NOT* public domain! *
- * Any provided source code is only for reference and for assurance *
- * that users should be able to compile FPL on any operating system *
- * he/she wants to use it in! *
- * *
- * You may not change, resource, patch files or in any way reverse *
- * engineer anything in the FPL package. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
- * *
- * Daniel Stenberg *
- * Ankdammsgatan 36, 4tr *
- * S-171 43 Solna *
- * Sweden *
- * *
- * FidoNet 2:201/328 email:dast@sth.frontec.se *
- * *
- ************************************************************************/
-
- #ifdef AMIGA
- #include <exec/types.h>
- #include <proto/exec.h>
- #include <stdlib.h>
-
- #include <proto/dos.h>
- #include <exec/execbase.h>
- #include <dos.h>
-
- #include "/funclib/funclib.h"
-
- #elif defined(UNIX)
- #include <sys/types.h>
- #endif
-
- #include "script.h"
- #include "debug.h"
- #include <stdio.h>
- #include <stddef.h>
- #include <limits.h>
-
- static ReturnCode INLINE SendMessage(struct Data *, struct fplMsg *);
- static ReturnCode REGARGS Ltostr(struct Data *scr, struct fplStr **,
- long, long);
- static ReturnCode REGARGS GetSymbols(struct Data *, long, long,
- struct fplSymbol **);
- static long REGARGS my_memicmp(char *, char *, long);
-
- /**********************************************************************
- *
- * ReturnCode CmpAssign()
- *
- * Performs a compound assign to the value the third argument points to.
- * The assign performed is the one with the operator specified in the fourth
- * argument eg, x, +, /, &, %, | etc, etc...
- *
- ***************/
-
- ReturnCode REGARGS
- CmpAssign(struct Data *scr,
- long val, /* right operand */
- long *value, /* return value pointer */
- long flags, /* variable flags */
- char operation)
- {
- ReturnCode ret;
- switch(operation) { /* check the type of the assign */
- case CHAR_PLUS:
- *value+=val;
- break;
- case CHAR_MINUS:
- *value-=val;
- break;
- case CHAR_MULTIPLY:
- *value*=val;
- break;
- case CHAR_DIVIDE:
- *value/=val;
- break;
- case CHAR_AND:
- *value&=val;
- break;
- case CHAR_OR:
- *value|=val;
- break;
- case CHAR_REMAIN:
- *value%=val;
- break;
- case CHAR_XOR:
- *value^=val;
- break;
- case CHAR_LESS_THAN:
- *value<<=val;
- break;
- case CHAR_GREATER_THAN:
- *value>>=val;
- break;
- case CHAR_ASSIGN:
- *value=val;
- break;
- default:
- CALL(Warn(scr, FPLERR_ILLEGAL_ASSIGN)); /* >warning< */
- *value=val; /* perform a straight assign! */
- break;
- }
- if(flags&FPL_VARIABLE_LESS32) {
- /* if using less than 32 bit */
- if(flags&FPL_CHAR_VARIABLE)
- *value=(long)((signed char)*value);
- else
- *value=(long)((signed short)*value);
- }
- return(FPL_OK);
- }
-
-
- /**********************************************************************
- *
- * StrAssign();
- *
- * Assign a string variable.
- *
- ********/
-
- ReturnCode REGARGS
- StrAssign(struct fplStr *app,
- struct Data *scr,
- struct fplStr **string,
- char append) /* TRUE or FALSE if append */
- {
- ReturnCode ret;
-
- if(!append) { /* if not append */
- /* Exchange this string with the old one in the variable! */
- if(*string) {
- /*
- * There is a string! Free any type!
- */
- FREE_KIND(*string);
- }
- if(!app) {
- GETMEM(app, sizeof(struct fplStr));
- memset(app, 0, sizeof(struct fplStr)); /* clean it! */
- }
- *string = app;
-
- } else { /* append string */
- if(! (app?app->len:0))
- /* we don't append zero length strings! */
- return FPL_OK;
-
- CALL(AppendStringToString(scr, string, app->string, app->len));
-
- }
- return(FPL_OK);
- }
-
- /************************************************************************
- *
- * AppendStringToString()
- *
- * Append a generic string to a fplStr.
- *
- */
-
- ReturnCode REGARGS
- AppendStringToString(struct Data *scr, /* common data struct */
- struct fplStr **string, /* variable to append to */
- char *append, /* string to append */
- long applen) /* length of append string */
- {
- long length;
- long alloc;
- long ln;
- struct fplStr *pek;
- ReturnCode ret;
- void *dest;
- char type = *string?TypeMem(*string):MALLOC_DYNAMIC;
-
- length=*string?(*string)->len:0;
- alloc=*string?(*string)->alloc:0;
-
- ln = applen + length; /* total length */
- if (ln>=alloc) { /* do we have that much memory allocated? */
- /*
- * Allocate new memory for string.
- */
-
- GETMEM(pek, sizeof(struct fplStr)+ln+ADDSTRING_INC);
- if(MALLOC_STATIC == type)
- SwapMem(scr, pek, MALLOC_STATIC);
-
- if(*string) {
- memcpy(pek, (*string), length+sizeof(struct fplStr));
- FREE_KIND(*string);
- } else
- pek->len=0;
- #ifdef DEBUG
- CheckMem(scr, pek);
- #endif
- (*string)=pek; /* the new pointer */
- (*string)->alloc=ln+ADDSTRING_INC; /* new allocated size */
- }
-
- dest=(void *)&(*string)->string[length];
-
- /* no string function... only mem-versions! */
- memcpy(dest, (void *)append, applen);
-
- (*string)->len += applen;
-
- (*string)->string[(*string)->len]=CHAR_ASCII_ZERO; /* zero terminate */
-
- return FPL_OK;
- }
-
-
- /************************************************************************
- *
- * ReturnChar()
- *
- * Returns the ASCII code of the character scr->text points to.
- *
- * Supports 100% ANSI C escape sequences.
- */
-
- ReturnCode REGARGS
- ReturnChar(struct Data *scr,
- long *num,
- char string) /* is this is within quotes */
- {
- ReturnCode ret=FPL_OK;
- long cont=TRUE, steps;
- *num=256;
- while(cont) {
- cont=FALSE;
- if(*scr->text==CHAR_BACKSLASH) {
- steps=2;
- switch(scr->text[1]) {
- case CHAR_B:
- *num=CHAR_BACKSPACE;
- break;
- case CHAR_T:
- *num=CHAR_TAB;
- break;
- case CHAR_N:
- *num=CHAR_NEWLINE;
- break;
- case CHAR_F:
- *num=CHAR_FORMFEED;
- break;
- case CHAR_BACKSLASH:
- *num=CHAR_BACKSLASH;
- break;
- case CHAR_QUOTATION_MARK:
- *num=CHAR_QUOTATION_MARK;
- break;
- case CHAR_APOSTROPHE:
- *num=CHAR_APOSTROPHE;
- break;
- case CHAR_A:
- *num=CHAR_ALERT;
- /* ^^^^ causes warnings ('warning: \a is ANSI C "alert" character')
- * on some compilers. Ignore and look happy!
- */
- break;
- case CHAR_R:
- *num=CHAR_CARRIAGE_RETURN;
- break;
- case CHAR_V:
- *num=CHAR_VERTICAL_TAB;
- break;
- case CHAR_QUESTION:
- *num=CHAR_QUESTION;
- break;
- case CHAR_X:
- steps=*num=0;
- for(scr->text+=2; steps++<2 && isxdigit(*scr->text); scr->text++)
- *num=*num*16+ (isdigit(*scr->text)?
- *scr->text-CHAR_ZERO:
- UPPER(*scr->text)-CHAR_UPPER_A+10);
- if(!steps)
- return(FPLERR_SYNTAX_ERROR); /* no number followed \x sequence */
- steps=0;
- break;
- case CHAR_ZERO:
- case CHAR_ONE:
- case CHAR_TWO:
- case CHAR_THREE:
- case CHAR_FOUR:
- case CHAR_FIVE:
- case CHAR_SIX:
- case CHAR_SEVEN:
- *num=steps=0;
- for(scr->text++;steps++<3 && isodigit(*scr->text);)
- *num=*num*8+ *scr->text++ - CHAR_ZERO;
- steps=0;
- break;
- case CHAR_NEWLINE:
- /* After a line continuation backslash, a newline is required!
- This is made to apply to the ANSI C escape sequence standard.
- (added 930113-1305 / DaSt) */
- cont=TRUE;
- scr->virprg++;
- break;
- default:
- /* Any character not identified as a escape sequence character
- will simply ignore the backslah character!
- (added 930113-1307 / DaSt) */
- *num=scr->text[1];
- break;
- }
- scr->text+=steps;
- } else if(!string && *scr->text=='\n') {
- /* This won't occur if the script is preprocessed! */
- cont=TRUE;
- scr->text++;
- } else if(*scr->text=='\0') {
- /* This won't occur if the script is preprocessed! */
- cont=TRUE;
- CALL(Newline(scr));
- } else {
- *num=*scr->text;
- scr->text++;
- }
- }
- return(ret);
- }
-
- /**********************************************************************
- *
- * ReturnCode NewMember(struct Expr **);
- *
- * This function adds a new member in the linked list which keeps
- * track on every operand and it's opertor in the expression.
- *
- *******/
-
- ReturnCode REGARGS
- NewMember(struct Data *scr,
- struct Expr **expr)
- {
- GETMEM((*expr)->next, sizeof(struct Expr));
-
- (*expr)=(*expr)->next;
- (*expr)->val.val=0;
- (*expr)->unary=NULL;
- (*expr)->operator=OP_NOTHING;
- (*expr)->flags=FPL_OPERAND;
- (*expr)->next=NULL;
- return(FPL_OK);
- }
-
-
- /**********************************************************************
- *
- * ReturnCode Warn();
- *
- * This routines calls the interface function to ask for permission to
- * continue the execution, even though error(s) has/have been found in
- * the interpreted program.
- *
- ******/
-
- ReturnCode REGARGS
- Warn(struct Data *scr,
- ReturnCode rtrn)
- {
- struct fplArgument *pass;
- struct fplMsg *msg;
- ReturnCode ret;
-
- GETMEM(pass, sizeof(struct fplArgument));
- pass->ID=FPL_WARNING;
- pass->key=scr;
- pass->argc=1;
- pass->argv=(void **)&rtrn; /* first ->argv member holds the error/warning number! */
-
- ret=InterfaceCall(scr, pass, scr->function);
-
- FREE(pass);
- GetMessage(scr, FPLMSG_CONFIRM, &msg);
- if(msg) {
- if(msg->message[0]) {
- rtrn=ret;
- scr->prog->warnings++;
- }
- DeleteMessage(scr, msg);
- }
- return(rtrn);
- }
-
-
- /**********************************************************************
- *
- * fplSend()
- *
- * Send a message to FPL.
- *
- ******/
-
- ReturnCode PREFIX fplSend(AREG(0) struct Data *scr,
- AREG(1) unsigned long *tags)
- {
- #ifdef DEBUGMAIL
- DebugMail(scr, MAIL_FUNCTION, 500, "fplSend");
- #endif
- return Send(scr, tags);
- }
-
- ReturnCode REGARGS Send(struct Data *scr,
- unsigned long *tags)
- {
- struct fplMsg msg;
- long len=-1;
- struct Program *prog;
- char *data=NULL;
- ReturnCode ret;
- struct fplSymbol *symbol;
- struct fplStr *string;
- long mixed;
- static long *resultcode=NULL;
- char fplallocstring=FALSE;
- if(!scr)
- return(FPLERR_ILLEGAL_ANCHOR);
-
- memset(&msg, 0, sizeof(struct fplMsg));
-
- while(tags && *tags) {
- switch(*tags++) {
-
- case FPLSEND_STRING:
- /* FPLSEND_PROGRAMFILE is the same tag */
- data=(void *)*tags;
- msg.type=FPLMSG_RETURN_STRING;
- break;
-
- case FPLSEND_STRLEN:
- len=(long)*tags;
- break;
-
- case FPLSEND_DONTCOPY_STRING: /* the string sent is fplAllocString()'ed */
- fplallocstring=(char)*tags;
- break;
-
- case FPLSEND_INT:
- msg.message[0]=(void *)*tags;
- msg.type=FPLMSG_RETURN_INT;
- break;
-
- case FPLSEND_PROGRAM:
- msg.message[0]=(void *)*tags;
- msg.type=FPLMSG_PROGRAM;
- break;
-
- case FPLSEND_CONFIRM:
- msg.type=FPLMSG_CONFIRM;
- msg.message[0]=(void *)*tags;
- break;
-
- case FPLSEND_GETINTERVAL:
- *(long *)*tags=(long)scr->interfunc;
- break;
-
- case FPLSEND_GETFUNCTION:
- *(long *)*tags=(long)scr->function;
- break;
-
- case FPLSEND_GETLINE:
- *(long *)*tags=scr->prg;
- break;
-
- case FPLSEND_GETVIRFILE:
- *(char **)*tags=scr->virfile;
- break;
-
- case FPLSEND_GETVIRLINE:
- *(long *)*tags=scr->virprg;
- break;
-
- case FPLSEND_GETNEWLINE_HOOK: /* OBSOLETE!!!! */
- break;
-
- case FPLSEND_GETRESULT:
- *(long *)*tags=scr->data;
- break;
-
- case FPLSEND_GETRETURNCODE:
- *(long *)*tags=scr->FPLret;
- break;
-
- case FPLSEND_GETRETURNINT: /* new from V10 */
- *(long **)*tags=scr->returnint;
- break;
-
- case FPLSEND_GETUSERDATA:
- *(long *)*tags=(long)scr->userdata;
- break;
-
- case FPLSEND_GETCOLUMN:
- if(scr->prog && scr->prog->running)
- *(long *)*tags=(scr->text-(&scr->prog->program)[scr->prg-1]+1);
- else if(scr->prog)
- /* we cannot count on this programs presence */
- *(long *)*tags=scr->prog->column;
- else
- *(long *)*tags=0; /* we don't know! */
- break;
-
- case FPLSEND_GETPROGNAME:
- if(scr->prog && scr->prog->name)
- *(char **)*tags=scr->prog->name;
- else /* we have no program information */
- *(char **)*tags=FPLTEXT_UNKNOWN_PROGRAM;
- break;
-
- case FPLSEND_GETPROG:
- if(scr->prog && scr->prog->program)
- *(char **)*tags=scr->prog->program;
- else /* we have no program information */
- *(char **)*tags=NULL;
- break;
-
- case FPLSEND_FLUSHCACHE:
- if(*tags)
- FlushFree(scr);
- break;
-
- case FPLSEND_FLUSHFILE:
- if(*tags) {
- prog=scr->programs;
- while(prog) {
- if(!strcmp(prog->name, (char *)*tags))
- break;
- prog=prog->next;
- }
- if(!prog)
- return(FPLERR_INTERNAL_ERROR);
- } else
- prog=scr->programs;
- while(prog) {
- if(!(prog->running)) {
- /* if the program isn't running right now! */
- len=prog->flags;
- prog->flags&=~PR_CACHEFILE; /* switch off the cache bit now */
- CALL(LeaveProgram(scr, prog));
- prog->flags=len; /* restore flag bits! */
- }
- if(*tags)
- /* only the specified */
- break;
- prog=prog->next;
- }
- break;
-
- case FPLSEND_FREEFILE:
- prog=scr->programs;
- while(prog) {
- if(!strcmp(prog->name, (char *)*tags))
- break;
- prog=prog->next;
- }
- if(!prog || prog->running || prog->openings)
- /* if not found or if the found one is currently in use! */
- return(FPLERR_ILLEGAL_PARAMETER);
- {
- for(mixed=0; mixed<scr->hash_size; mixed++) {
- register struct Identifier *nident;
- register struct Identifier *ident = scr->hash[mixed];
- while(ident) {
- nident=ident->next;
- if(!strcmp(ident->file, (char *)*tags))
- DelIdentifier(scr, NULL, ident);
- ident=nident;
- }
- }
- }
- DelProgram(scr, prog);
- break;
-
- case FPLSEND_STEP:
- if(*tags>0) {
- while((*tags)--) {
- if(!*scr->text)
- CALL(Newline(scr));
- scr->text++;
- }
- } else if((signed int)(*tags)<0) {
- while((*tags)++) {
- if( (scr->text-(&scr->prog->program)[scr->prg-1])>=0)
- scr->text--;
- else
- if(scr->prg>1)
- scr->text=(&scr->prog->program)[--scr->prg-1];
- else
- return(FPLERR_UNEXPECTED_END);
- }
- }
- break;
- case FPLSEND_GETSYMBOL_FUNCTIONS:
- CALL(GetSymbols(scr, FPL_EXTERNAL_FUNCTION|FPL_INSIDE_FUNCTION,
- FPL_EXPORT_SYMBOL,
- (struct fplSymbol **)*tags));
- break;
- case FPLSEND_GETSYMBOL_MYFUNCTIONS:
- CALL(GetSymbols(scr, FPL_EXTERNAL_FUNCTION, FPL_FUNCTION,
- (struct fplSymbol **)*tags));
- break;
- case FPLSEND_GETSYMBOL_FPLFUNCTIONS:
- CALL(GetSymbols(scr, FPL_EXPORT_SYMBOL, FPL_INSIDE_FUNCTION,
- (struct fplSymbol **)*tags));
- break;
- case FPLSEND_GETSYMBOL_VARIABLES:
- CALL(GetSymbols(scr, FPL_EXPORT_SYMBOL, FPL_VARIABLE,
- (struct fplSymbol **)*tags));
- break;
- case FPLSEND_GETSYMBOL_ALLVARIABLES:
- CALL(GetSymbols(scr, ~0, FPL_VARIABLE, (struct fplSymbol **)*tags));
- break;
-
- case FPLSEND_GETSYMBOL_ALLFUNCTIONS:
- CALL(GetSymbols(scr, ~0, FPL_FUNCTION, (struct fplSymbol **)*tags));
- break;
-
- case FPLSEND_GETSYMBOL_CACHEDFILES:
- prog=scr->programs;
- mixed=0;
- while(prog) {
- if(prog->flags&PR_CACHEFILE)
- mixed++;
- prog=prog->next;
- }
-
- GETMEM(symbol, sizeof(struct fplSymbol));
- symbol->num=mixed;
- GETMEM(symbol->array, mixed*sizeof(char *));
-
- mixed=0;
- prog=scr->programs;
- while(prog) {
- if(prog->flags&PR_CACHEFILE)
- symbol->array[mixed++]=prog->name;
- prog=prog->next;
- }
- *(struct fplSymbol **)*tags=symbol;
-
- #ifdef DEBUG
- CheckMem(scr, symbol);
- CheckMem(scr, symbol->array);
- #endif
-
- break;
-
- /* ---------------- new from V10: --------------------- */
-
- case FPLSEND_RESULT:
- resultcode = (long *)(*tags); /* long to store result in! */
- break;
-
- case FPLSEND_IS_FILE_CACHED:
- if(resultcode) {
- prog=scr->programs;
- while(prog) {
- if(prog->name && !strcmp(prog->name, (char *)(*tags))) {
- *resultcode = TRUE;
- break;
- }
- prog=prog->next;
- }
- *resultcode = FALSE;
- }
- break;
-
- /* --------------------------------------------------- */
-
- case FPLSEND_GETSYMBOL_FREE:
- #ifdef DEBUG
- CheckMem(scr, (void *)(*tags));
- CheckMem(scr, ((struct fplSymbol *)*tags)->array);
- #endif
- FREE(((struct fplSymbol *)*tags)->array);
- FREE(*tags);
- break;
-
- #if defined(AMIGA) && defined(SHARED)
- case FPLSEND_GETSTACKSIZE:
- *(long *)*tags=scr->stack_size;
- break;
- case FPLSEND_GETSTACKUSED:
- *(long *)*tags=GetStackUsed(scr);
- break;
- #endif
-
- case FPLSEND_SETPROGNAME:
- if(scr->prog) {
- if(scr->prog->name)
- FREEA(scr->prog->name);
- STRDUPA(scr->prog->name, *tags);
- }
- break;
-
- case FPLSEND_SETFILENAMEGET:
- if(scr->prog) {
- if(*tags)
- scr->prog->flags|=PR_FILENAMEFLUSH;
- else
- scr->prog->flags&=~PR_FILENAMEFLUSH;
- }
- break;
- }
- tags++;
- }
- if(!msg.type)
- /*
- * There is no message to send. Everything we had to do is done!
- */
- return(FPL_OK);
-
- if(msg.type==FPLMSG_RETURN_STRING) {
- if(len<0)
- if(data)
- len=strlen(data);
- if(!len || !data)
- /* this really is a zero length string! */
- msg.message[0]=NULL;
- else {
- if(!fplallocstring) {
- /* we have to duplicate the data */
- GETMEM(msg.message[0], len+sizeof(struct fplStr));
- string=msg.message[0];
- string->len=len;
- string->alloc=len;
- memcpy(string->string, data, len); /* copy string! */
- string->string[string->len]=CHAR_ASCII_ZERO; /* zero terminate */
- } else {
- /* the data was sent as fplAllocString() data! */
- string= (struct fplStr *)(data - offsetof(struct fplStr, string));
- string->len=len;
- string->string[string->len]=CHAR_ASCII_ZERO; /* zero terminate */
- SwapMem(scr, string, MALLOC_DYNAMIC); /* convert */
- msg.message[0]=string;
- }
- }
- }
- CALL(SendMessage(scr, &msg));
- return(ret);
- }
-
-
- /*********************************************************************
- *
- * fplConvertString()
- *
- * Returns the number of characters converted from the FPL format
- * string to the binary sting stored in a buffer.
- *
- * The output string always get zero terminated!
- *
- *****/
-
- long PREFIX
- fplConvertString(AREG(0) struct Data *scr,
- AREG(1) char *string,
- AREG(2) char *buffer)
- {
- long prg=scr->prg;
- char *text=scr->text;
- long line;
- char *base;
- long a;
- long number=0;
-
- #ifdef DEBUGMAIL
- DebugMail(scr, MAIL_FUNCTION, 500, "fplConvertString");
- #endif
-
- if(!scr->prog) {
- /*
- * There is no program at the moment!
- * create a pseudo program for now!
- */
- scr->prog=(struct Program *)MALLOC(sizeof(struct Program));
- if(!scr->prog)
- return(0); /* no characters in output! */
- scr->prog->flags|=PR_TEMPORARY;
- }
-
- base=scr->prog->name;
- line=scr->prog->lines;
- /*
- if(*string==CHAR_QUOTATION_MARK)
- string++;
- */
-
- scr->prg=1;
- scr->text=string;
- scr->prog->lines=1;
- scr->prog->name=NULL; /* we have no file ID yet! */
-
- while(/* *scr->text!=CHAR_QUOTATION_MARK && */
- !ReturnChar(scr, &a, TRUE)) { /* returns non-zero when an ascii zero is
- found! */
- *buffer++=a;
- number++;
- }
-
- *buffer=CHAR_ASCII_ZERO;
-
- scr->prg=prg;
- scr->text=text;
- scr->prog->lines=line;
- scr->prog->name=base;
-
- if(scr->prog->flags&PR_TEMPORARY) {
- FREE(scr->prog);
- scr->prog=NULL;
- }
-
- return(number);
- }
-
- /**********************************************************************
- *
- * GetSymbols();
- *
- * Allocates a structure and data, which is a list of name pointers
- * that match the flag parameter.
- *
- *******/
-
- static ReturnCode REGARGS
- GetSymbols(struct Data *scr,
- long flag1,
- long flag2,
- struct fplSymbol **get)
- {
- long i;
- long num;
- struct Identifier *ident;
- struct fplSymbol *symbol;
-
- for(i=num=0; i<FPL_HASH_SIZE; i++) {
- ident=scr->hash[i];
- while(ident) {
- if(ident->flags&flag1 && ident->flags&flag2)
- num++;
- ident=ident->next;
- }
- }
-
- GETMEM(symbol, sizeof(struct fplSymbol));
- symbol->num=num;
-
- GETMEM(symbol->array, sizeof(char *)*symbol->num);
-
- for(i=num=0; i<FPL_HASH_SIZE; i++) {
- ident=scr->hash[i];
- while(ident) {
- if(ident->flags&flag1 && ident->flags&flag2)
- symbol->array[num++]=ident->name;
- ident=ident->next;
- }
- }
- *get=symbol;
-
- #ifdef DEBUG
- CheckMem(scr, symbol->array);
- #endif
- return(FPL_OK);
- }
-
-
- /**********************************************************************
- *
- * SendMessage();
- *
- * Add a member to the message queue. Allocate a new struct and copy the
- * data of from second parameter message pointer.
- *
- ******/
-
- static ReturnCode INLINE
- SendMessage(struct Data *scr,
- struct fplMsg *msg)
- {
- struct fplMsg *NewMsg, *ptr;
-
- GETMEM(NewMsg, sizeof(struct fplMsg));
-
- *NewMsg=*msg; /* copy all data from source */
-
- /* Queue the message: */
- if(ptr=scr->msg)
- ptr->prev=NewMsg; /* this message becomes the previous for this */
-
- scr->msg=NewMsg;
- NewMsg->next=ptr;
- NewMsg->prev=NULL; /* no previous, this is first! */
-
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * DeleteMessage();
- *
- * Deletes specified or current message (NULL).
- *
- *****/
-
- ReturnCode REGARGS
- DeleteMessage(struct Data *scr,
- struct fplMsg *msg)
- {
- struct fplMsg *ptr=scr->msg;
- if(msg)
- ptr=msg;
- if(ptr) {
- if(ptr->next)
- ptr->next->prev=ptr->prev; /* redirect next message's prev pointer */
- else if(!ptr->prev) /* is this the only message? */
- scr->msg=NULL;
- if(ptr->prev)
- ptr->prev->next=ptr->next; /* redirect previous message's next pointer */
- FREE(ptr); /* free message */
- }
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * GetMessage()
- *
- * Returns the first message of the requested type in the pointer
- * in the third argument!
- *
- ****/
-
- ReturnCode REGARGS
- GetMessage(struct Data *scr,
- char type,
- struct fplMsg **get)
- {
- struct fplMsg *msg=scr->msg;
- while(*get=msg) {
- if(msg->type==type)
- break;
- msg=msg->next;
- }
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * GetProgram();
- *
- * Whenever we want to access a program in the program list, we do it
- * using this function. This enables heavy program swapping capabilities.
- * Programs that are not being used can be flushed from memory and brought
- * back whenever we need it!
- *
- ******/
-
- ReturnCode REGARGS
- GetProgram(struct Data *scr,
- struct Program *prog)
- {
- struct fplArgument *arg;
- ReturnCode ret;
- struct fplMsg *msg;
- struct fplStr *string;
- if(!prog->program) {
- /*
- * The program is not currently in memory. Get it!
- */
-
- if(prog->flags&PR_FILENAMEFLUSH) {
- /*
- * We know that the program is simply to load from the file the program
- * name specifies.
- */
- CALL(ReadFile(scr, prog->name, prog));
- } else {
- /*
- * We must ask user for information!
- */
-
- GETMEM(arg, sizeof(struct fplArgument));
- arg->ID=FPL_FILE_REQUEST;
- arg->key=(void *)scr;
- arg->argv=(void **)&prog->name;
- arg->argc=1;
- ret=InterfaceCall(scr, arg, scr->function);
- FREE(arg);
- if(ret)
- return ret;
-
- GetMessage(scr, FPLMSG_PROGRAM, &msg);
- if(!msg) {
- GetMessage(scr, FPLMSG_RETURN_STRING, &msg);
- if(!msg)
- /*
- * No kind of proper answer could be found!
- * Dead end failure!
- */
- return(FPLERR_INTERNAL_ERROR);
-
- string=(struct fplStr *)msg->message[0];
- ret = ReadFile(scr, string->string, prog);
- FREE(msg->message[0]); /* we don't need this anymore! */
- if(ret)
- return ret;
- } else {
- /*
- * User supplied us with a memory pointer to the program again!
- */
- prog->program= (char *)msg->message[0];
- prog->flags|=PR_USERSUPPLIED;
- }
- DeleteMessage(scr, msg);
- }
- } /* else
- we already have it loaded! */
- prog->running++;
- return(FPL_OK);
- }
-
-
- /**********************************************************************
- *
- * LeaveProgram();
- *
- * If we leave one program, call this. If any flush is to be done, this
- * will perform that!
- *
- ******/
-
- ReturnCode REGARGS
- LeaveProgram(struct Data *scr,
- struct Program *prog)
- {
- struct fplArgument *arg;
- ReturnCode ret;
- struct fplMsg *msg;
- prog->running--;
- if(prog->program && !prog->running && prog->flags&PR_FLUSH_NOT_IN_USE) {
- /*
- * The program is there and no one is using it!
- * flush it if we want to!
- */
-
- if(prog->flags&PR_USERSUPPLIED) {
- /*
- * This program is supplied by the external program. We cannot
- * free the memory, only tell our father that freeing is OK...
- */
- GETMEM(arg, sizeof(struct fplArgument));
- arg->ID=FPL_FLUSH_FILE;
- arg->key=(void *)scr;
- arg->argv=(void **)&prog->name;
- arg->argc=1;
- CALL(InterfaceCall(scr, arg, scr->function));
- FREE(arg);
- GetMessage(scr, FPLMSG_CONFIRM, &msg);
- /*
- * We require a {FPLSEND_CONFIRM, TRUE} message from the user before we
- * flush the user supplied function! Simply ignore implementing any
- * answer to this message if we never want to flush user supplied
- * functions.
- */
- if(msg && msg->message[0])
- /* If we got a "OK" message! */
- prog->program=NULL;
- if(msg)
- DeleteMessage(scr, msg);
- } else {
- /*
- * The memory occupied by this program is our business.
- * Swap the memory first to be sure we know the kind of it!
- */
- SwapMem(scr, prog->program, MALLOC_DYNAMIC);
- FREE(prog->program);
- prog->program=NULL; /* to visualize the clearing of this program! */
- }
- }
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * int functions(struct fplArgument *);
- *
- * This function handles the internal functions. *EXACTLY* the same way
- * external processes handles their functions!!! :-)
- *
- *****/
-
- ReturnCode REGARGS
- functions(struct fplArgument *arg)
- {
- struct Expr *val;
- unsigned long inttags[]={FPLSEND_INT, 0, FPLSEND_DONE};
- unsigned long strtags[]={FPLSEND_STRING, 0, FPLSEND_STRLEN, 0, FPLSEND_DONE};
- long base;
- ReturnCode ret;
- struct Data *scr=(struct Data *)arg->key;
- struct fplStr *string;
- long prg;
- long line;
- long virprg;
- char *virfile;
- char *text;
- /* char *file; */
- long len; /* length of the string */
- register long col; /* the column parameter */
- switch(arg->ID) {
-
- case FNC_ABS:
- inttags[1]= ABS((long)arg->argv[0]);
- CALL(Send(arg->key, inttags));
- break;
-
- case FNC_ITOC:
- prg=(long)arg->argv[0]&255;
- text=(char *)&line; /* we just need 2 bytes to play with in peace! */
- text[1]='\0';
- text[0]=prg;
- strtags[1]=(long)text;
- strtags[3]=1;
- CALL(Send(scr, strtags));
- break;
-
- case FNC_JOINSTR:
- string=NULL;
- for(prg=0; prg<arg->argc; prg++) {
- CALL(StrAssign((struct fplStr *) ((char *)arg->argv[prg]-
- offsetof(struct fplStr, string)),
- scr, &string, TRUE));
- }
- if(string) {
- strtags[1]=(unsigned long)string->string;
- strtags[3]=string->len;
- CALL(Send(scr, strtags));
- FREE(string);
- }
- break;
-
- case FNC_ITOA:
- case FNC_LTOSTR:
- base=(arg->argc<2?10:(long)arg->argv[1]);
- CALL(Ltostr(scr, &string, base, (long)arg->argv[0]));
- strtags[1]=(unsigned long)string->string;
- strtags[3]=string->len;
- CALL(Send(scr, strtags));
- FREE(string);
- break;
-
- case FNC_ATOI:
- case FNC_STRTOL:
- base=(arg->argc<2?10:(long)arg->argv[1]);
- inttags[1]= Strtol((char *)arg->argv[0], base, &text);
- CALL(Send(scr, inttags));
- break;
-
- case FNC_EVAL:
- prg=scr->prg;
- text=scr->text;
- line=scr->prog->lines;
- virprg=scr->virprg;
- virfile=scr->virfile;
-
- scr->virprg=1;
- scr->virfile=NULL;
- scr->text=(char *)arg->argv[0];
- scr->prg=scr->prog->lines=1;
-
- GETMEM(val, sizeof(struct Expr));
- CALL(Expression(val, scr, CON_GROUNDLVL|CON_END|CON_NUM, NULL));
- inttags[1]=val->val.val;
- FREE(val);
-
- scr->prg=prg;
- scr->text=text;
- scr->prog->lines=line;
- scr->virprg=virprg;
- scr->virfile=virfile;
-
- CALL(Send(scr, inttags));
- break;
-
- case FNC_INTERPRET:
- prg=scr->prg;
- text=scr->text;
- line=scr->prog->lines;
- /* file=scr->prog->name; */
- virprg=scr->virprg;
- virfile=scr->virfile;
- scr->virprg=1;
- scr->virfile=NULL;
- scr->interpret=NULL; /* nothing recursive here, no no! */
- scr->prg=1;
- scr->text=(char *)arg->argv[0];
- scr->prog->lines=1;
- /* scr->prog->name=NULL; */ /* we have no file name! */
-
- GETMEM(val, sizeof(struct Expr));
- ret=Script(scr, val, SCR_NORMAL, NULL);
- inttags[1]=val->val.val;
- FREE(val);
-
- if(ret) {
- /*
- * Check if the error occurred somewhere in the real program
- * or if it was within the argument. If within argument, we
- * set back the previous program pointer, otherwise not.
- */
- for(base=0;base<line;base++)
- if(scr->text>(&scr->prog->program)[base] &&
- scr->text<((&scr->prog->program)[base]+
- strlen((&scr->prog->program)[base])))
- break;
- if(base==line) {
- scr->prg=prg;
- scr->text=text;
- scr->prog->lines=line;
- /* scr->prog->name=file; */
- }
- return(ret);
- }
- scr->prg=prg;
- scr->text=text;
- scr->prog->lines=line;
- /* scr->prog->name=file; */
- scr->virprg=virprg;
- scr->virfile=virfile;
- CALL(Send(arg->key, inttags));
- break;
-
- case FNC_STRCMP:
- case FNC_STRICMP:
- /*
- * strcmp() with strings that can include a zero byte must use
- * memcmp(), but that also takes a third length argument which
- * must never be larger than the smallest of the two compared
- * strings!
- */
- line = MIN(FPL_STRING_LENGTH(arg, 0), FPL_STRING_LENGTH(arg, 1)); /* len */
-
- if(FNC_STRCMP == arg->ID)
- base = memcmp(arg->argv[0], arg->argv[1], line);
- else
- base = my_memicmp(arg->argv[0], arg->argv[1], line);
-
- if(!base && FPL_STRING_LENGTH(arg, 0) != FPL_STRING_LENGTH(arg, 1)) {
- /* similar strings after 'line' characters */
-
- /*
- * The strings are of different length.
- */
-
- base = ((char *)arg->argv[0])[line] -
- (FPL_STRING_LENGTH(arg, 1)>line?
- ((char *)arg->argv[1])[line] : 0 );
-
- if(!base) {
- /* only possible since FPL strings can hold zeroes! */
- base = 256; /* not possible in regular C */
- }
- }
- inttags[1]=base;
- CALL(Send(scr, inttags));
- break;
-
- case FNC_SUBSTR:
- len=FPL_STRING_LENGTH(arg, 0);
- col=(long)arg->argv[1];
- if(col>len || col<0) {
- strtags[1]=(unsigned long)NULL; /* we can't get any string! */
- } else {
- len-=col; /* Maximum length we can get */
- strtags[3]=((long)arg->argv[2]>len?len:(long)arg->argv[2]); /* strlen */
- strtags[1]=(long) arg->argv[0]+col; /* return string from here */
- }
- CALL(Send(scr, strtags));
- break;
-
- case FNC_STRLEN:
- inttags[1]=FPL_STRING_LENGTH(arg, 0);
- CALL(Send(scr, inttags));
- break;
-
- case FNC_STRNCMP:
- case FNC_STRNICMP:
- /*
- * strncmp() with strings that can include a zero byte must use
- * memcmp(), that also takes a third length argument which
- * must never be larger than the smallest of the two compared
- * strings or the number specified!
- */
- if(FNC_STRNCMP == arg->ID) {
- inttags[1]=
- memcmp(arg->argv[0], arg->argv[1],
- MIN3((long)arg->argv[2],
- FPL_STRING_LENGTH(arg, 0), FPL_STRING_LENGTH(arg, 1)));
- }
- else {
- inttags[1]=
- my_memicmp(arg->argv[0], arg->argv[1],
- MIN3((long)arg->argv[2],
- FPL_STRING_LENGTH(arg, 0), FPL_STRING_LENGTH(arg, 1)));
- }
- CALL(Send(scr, inttags));
- break;
-
- case FNC_STRSTR:
- case FNC_STRISTR:
- /*
- * strstr() should compare two memory regions, like a memmem()!
- * Code an own!
- */
- base = FPL_STRLEN(arg->argv[0]);
- line = FPL_STRLEN(arg->argv[1]);
- text = (char *)arg->argv[0];
-
- /*
- * Addition from FPL version 9:
- * starting search column in third parameter!
- */
- if(arg->argc>2) {
- if((int)arg->argv[2] < base) {
- text+=(int)arg->argv[2];
- base-=(int)arg->argv[2];
- }
- else {
- /* tried to start searching outside the string! */
-
- line = 1; /* to make a not-found return code */
- base = 0;
- }
- }
-
- if(line && base) {
- if(FNC_STRSTR == arg->ID) {
- /* Case sensitive */
- while(base-->=line) {
- if(!memcmp(text, (char *)arg->argv[1], line)) {
- line=0;
- break;
- }
- text++;
- }
- }
- else {
- /* Case insensitive */
- while(base-->=line) {
- if(!my_memicmp(text, (char *)arg->argv[1], line)) {
- line=0;
- break;
- }
- text++;
- }
- }
- }
- inttags[1]=line?-1:text-(char *)arg->argv[0];
-
- /* OLD ONE:
- text=(char *)strstr((char *)arg->argv[0], (char *)arg->argv[1]);
- inttags[1]=text?text-(char *)arg->argv[0]:-1;
- */
- CALL(Send(scr, inttags));
- break;
-
- case FNC_SPRINTF:
- {
- static unsigned long tags[]={
- FPLSEND_STRING, 0,
- FPLSEND_STRLEN, 0,
- FPLSEND_DONTCOPY_STRING, TRUE,
- FPLSEND_DONE
- };
- string = NULL;
- CALL(Sprintf(scr, &string, arg->argv[0], arg->argv, arg->format));
- tags[1] = (long)string->string;
- tags[3] = string->len;
- CALL(Send(scr, tags));
- }
- break;
-
- #if defined(AMIGA)
- case FNC_OPENLIB:
- CALL(OpenLib(scr,
- (char *)arg->argv[0], /* name */
- (long)arg->argv[1], /* version */
- (long *)&inttags[1], /* funclib result */
- 0)); /* normal 'soft' open */
- CALL(Send(scr, inttags));
- break;
-
- case FNC_CLOSELIB:
- CALL(CloseLib(scr,
- (char *)arg->argv[0], /* name */
- 0, /* 'soft' close */
- (long *)&inttags[1])); /* funclib result */
- CALL(Send(scr, inttags));
- break;
-
- case FNC_DEBUG:
- if(arg->argc) {
- if(!(int)arg->argv[0]) {
- scr->flags&=~FPLDATA_DEBUG_MODE; /* switch off debug mode */
- #ifdef DEBUGMAIL
- /* DebugMail(scr, MAIL_EXIT, 500, NULL); */
- #endif
- }
- else {
- scr->flags|=FPLDATA_DEBUG_MODE; /* switch on debug mode */
- #ifdef DEBUGMAIL
- /* DebugMail(scr, MAIL_START, 500, NULL); */
- #endif
- }
- }
- else {
- inttags[1]=scr->flags&FPLDATA_DEBUG_MODE?1:0; /* return status */
- CALL(Send(scr, inttags));
- }
- break;
- #endif
- }
- return(FPL_OK);
- }
-
- #if defined(AMIGA)
- ReturnCode REGARGS
- OpenLib(struct Data *scr,
- char *lib, /* funclib name */
- long version, /* funclib version */
- long *retvalue, /* funclib return code */
- char flags)
- {
- struct MyLibrary *library;
- struct Library *DOSBase;
- BPTR seglist;
- char *command;
- char *cmd;
- struct FuncList *namelist=scr->funclibs;
- char *name;
- ReturnCode ret;
- struct fplStr *string;
-
- struct ExecBase *SysBase = *(struct ExecBase **)4;
-
- library = (struct MyLibrary *)getreg(REG_A6);
- DOSBase = library->ml_DosBase;
-
- GETMEM(command, FPLLIB_MAXSPACE);
-
- while(namelist) {
- if(!strcmp(namelist->name, lib)) {
- namelist->opens++;
- return FPL_OK; /* this funclib is already opened */
- }
- namelist = namelist->next;
- }
-
- cmd = command;
- strcpy(command, FPLLIB_SOURCE);
- strcpy(command+strlen(FPLLIB_SOURCE), lib);
- seglist = LoadSeg(command); /* load the command! */
- if(seglist) {
- strcpy(command, FPLLIB_OPENCMD);
- command += strlen(FPLLIB_OPENCMD);
-
- CALL(Ltostr(scr, &string, 10, (long)scr));
- strcpy(command, string->string);
- command[string->len]= ' '; /* pad with a single space */
- command+=string->len+1;
- FREE(string);
-
- CALL(Ltostr(scr, &string, 10, version));
- strcpy(command, string->string);
- command[string->len]= '\n'; /* add newline */
- command[string->len+1]= '\0'; /* zero terminate */
- FREE(string);
-
- if(SysBase->SoftVer<36) {
- /* V33 solution! */
- char *segment = BADDR(seglist);
- int (*func)();
- #pragma msg 147 ignore
- func = segment + 4; /* generates warning */
- #pragma msg 147 warning
-
- putreg(REG_A0, (long)cmd);
- putreg(REG_D0, strlen(cmd));
- #pragma msg 154 ignore
- *retvalue = (func)(); /* generates warning */
- #pragma msg 154 warning
- } else /* version 36 or up! */
- *retvalue = RunCommand(seglist, 4000, cmd, strlen(cmd));
-
- UnLoadSeg( seglist );
- } else {
- /* we failed loading the command! */
- *retvalue = FUNCLIB_LOAD;
- }
-
- FREE(cmd);
-
- if(!*retvalue) {
- GETMEMA(namelist, sizeof(struct FuncList));
- STRDUPA(name, lib);
- namelist->name = name;
- namelist->opens = 1;
- namelist->flags = flags;
- namelist->next = scr->funclibs;
- scr->funclibs = namelist;
- }
- return FPL_OK;
- }
-
- ReturnCode REGARGS
- CloseLib(struct Data *scr,
- char *lib, /* funclib name or NULL for all */
- long flags, /* options */
- long *retvalue) /* funclib return code */
- {
- struct MyLibrary *library;
- struct Library *DOSBase;
- struct FuncList *namelist=scr->funclibs;
- struct FuncList *prevlist=NULL;
- struct FuncList *next;
- char *command;
- char *cmd;
- ReturnCode ret;
- struct fplStr *string;
- BPTR seglist;
-
- struct ExecBase *SysBase = *(struct ExecBase **)4;
-
- library = (struct MyLibrary *)getreg(REG_A6);
- DOSBase = library->ml_DosBase;
-
- GETMEM(command, FPLLIB_MAXSPACE);
- cmd = command;
-
- while(namelist) {
- if(namelist->flags&FPLLIB_KEEP && namelist->opens==1) {
- /* This funclib is prevented from being 'soft' closed! */
- namelist->opens++;
- }
- if((!lib || !strcmp(namelist->name, lib)) &&
- (!--namelist->opens || flags&FPLLIB_FORCE) ) {
- /* the funclib _is_ opened! */
-
- strcpy(command, FPLLIB_SOURCE);
- strcpy(command+strlen(FPLLIB_SOURCE), lib);
- seglist = LoadSeg(command); /* load the command! */
- if(seglist) {
- strcpy(command, FPLLIB_CLOSECMD);
- command += strlen(FPLLIB_CLOSECMD);
-
- CALL(Ltostr(scr, &string, 10, (long)scr));
- strcpy(command, string->string);
- command[string->len]= '\n'; /* add newline */
- command[string->len+1]= '\0'; /* zero terminate */
- FREE(string);
-
- if(SysBase->SoftVer<36) {
- /* V33 solution! */
- char *segment = BADDR(seglist);
- int (*func)();
- #pragma msg 147 ignore
- func = segment + 4; /* generates warning */
- #pragma msg 147 warning
-
- putreg(REG_A0, (long)cmd);
- putreg(REG_D0, strlen(cmd));
- #pragma msg 154 ignore
- *retvalue = (func)(); /* generates warning */
- #pragma msg 154 warning
- } else /* version 36 or up! */
- *retvalue = RunCommand(seglist, 4000, cmd, strlen(cmd));
-
- UnLoadSeg( seglist );
- } else {
- /* we failed loading the command! */
- *retvalue = FUNCLIB_LOAD;
- }
-
-
- if(!*retvalue) {
- next = namelist->next;
- if(prevlist) /* was there a previous funclib in the list? */
- prevlist->next=next; /* point it to the next in the list */
- else
- scr->funclibs = next; /* point the origin to the next */
- FREEA(namelist->name); /* free name space */
- FREEA(namelist); /* free struct */
- namelist = next;
- continue;
- }
- }
- prevlist = namelist;
- namelist = namelist->next;
- }
-
- FREE(cmd);
-
- return FPL_OK;
- }
-
- #endif
-
- /**********************************************************************
- *
- * fplLtostr()
- *
- * Frontend to the FPL Ltostr() function to be used by anyone! The returned
- * string *must* be freed using the fplFreeString() function!
- *
- ****/
-
- char * PREFIX
- fplLtostr(AREG(0) struct Data *scr,
- DREG(0) long base,
- DREG(1) long num)
- {
- ReturnCode ret;
- struct fplStr *string;
- char *retstring=NULL;
- #ifdef DEBUGMAIL
- DebugMail(scr, MAIL_FUNCTION, 500, (void *)"fplLtostr");
- #endif
- ret = Ltostr(scr, &string, base, num);
- if(FPL_OK == ret) {
- SwapMem(scr, string, MALLOC_STATIC); /* turn allocation to static type */
- retstring = string->string; /* return string pointer */
- }
- return retstring;
- }
-
-
- static ReturnCode REGARGS
- Ltostr(struct Data *scr,
- struct fplStr **string,
- long base,
- long num)
- {
- /*
- * Convert the integer to string with `any base'-convertions.
- */
- extern const char upper_digits[];
- ReturnCode ret;
- static const char *digits = upper_digits;
- long is_neg=num<0;
- long len=0;
- char buffer[34+sizeof(struct fplStr)];
- char *bufpoint; /* the accurate position in the buffer */
-
- if(base>strlen(digits)) {
- CALL(Warn(scr, FPLERR_OUT_OF_REACH));
- num=strlen(digits); /* reset to maximum */
- }
- num=ABS(num);
-
- buffer[33+sizeof(struct fplStr)]=CHAR_ASCII_ZERO; /* zero byte termination */
- bufpoint=&buffer[33+sizeof(struct fplStr)]; /* start digit output position */
-
- if(num) {
- while(num>0) {
- *--bufpoint= digits[num % base];
- num /= base;
- len++;
- }
- if(is_neg) {
- *--bufpoint='-';
- len++;
- }
- } else {
- *--bufpoint=CHAR_ZERO;
- len++;
- }
-
- GETMEM(*string, len+sizeof(struct fplStr));
- strcpy((*string)->string, bufpoint);
- (*string)->len=len;
- (*string)->alloc=len;
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * fplStrtol()
- *
- * Frontend to the FPL Strtol() function to be used by anyone!
- *
- ****/
-
- long PREFIX
- fplStrtol(AREG(0) char *string,
- DREG(0) long base,
- AREG(1) char **end)
- {
- /*
- * THIS CAN'T CURRENT CALL DEBUGMAIL SINCE NO struct Data IS USED!!!
- */
- return Strtol(string, base, end);
- }
-
- /**********************************************************************
- *
- * Strtol()
- *
- * String to long integer. Code copied and changed from the GNU libc
- * source code package.
- *
- ****/
-
- long REGARGS
- Strtol(char *nptr,
- long base,
- char **end)
- {
- char negative;
- unsigned long cutoff;
- unsigned long cutlim;
- long i;
- char *s;
- unsigned char c;
- char *save;
- long overflow;
-
- if (base < 0 || base == 1 || base > 36)
- base = 10;
-
- s = nptr;
-
- /* Skip white space. */
- while(isspace(*s))
- s++;
-
- if (*s == CHAR_ASCII_ZERO)
- return (0);
-
- /* Check for a sign. */
- else if (*s == CHAR_MINUS) {
- negative = 1;
- ++s;
- } else if (*s == CHAR_PLUS) {
- negative = 0;
- ++s;
- } else
- negative = 0;
-
- if ((base == 16 && s[0] == CHAR_ZERO && UPPER(s[1]) == CHAR_UPPER_X) ||
- (base == 2 && s[0] == CHAR_ZERO && UPPER(s[1]) == CHAR_UPPER_B) )
- s += 2;
-
- /* If BASE is zero, figure it out ourselves. */
- if (base == 0)
- if (*s == '0') {
- switch(UPPER(s[1])) {
- case CHAR_UPPER_X:
- s += 2;
- base = 16;
- break;
- case CHAR_UPPER_B:
- s += 2;
- base = 2;
- break;
- default:
- base = 8;
- break;
- }
- } else
- base = 10;
-
- /* Save the pointer so we can check later if anything happened. */
- save = s;
-
- cutoff = ULONG_MAX / (unsigned long int) base;
- cutlim = ULONG_MAX % (unsigned long int) base;
-
- overflow = 0;
- i = 0;
- for (c = *s; c; c = *++s) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c = UPPER(c) - CHAR_UPPER_A + 10;
- else
- break;
- if (c >= base)
- break;
- /* Check for overflow. */
- if (i > cutoff || (i == cutoff && c > cutlim))
- overflow = 1;
- else {
- i *= (unsigned long int) base;
- i += c;
- }
- }
-
- *end=s; /* this is the end position of the number */
-
- /* Check if anything actually happened. */
- if (s == save)
- return (0);
-
- /* Check for a value that is within the range of
- `unsigned long int', but outside the range of `long int'. */
- if (i > (negative ?
- - (unsigned long int) LONG_MIN :
- (unsigned long int) LONG_MAX))
- overflow = 1;
-
- if (overflow)
- return negative ? LONG_MIN : LONG_MAX;
-
- /* Return the result of the appropriate sign. */
- return (negative ? - i : i);
- }
-
- /*****************************************************************************
- *
- * my_memicmp()
- *
- * This makes a case insensitive memcmp() with the very same parameters.
- *
- *********/
-
- static long REGARGS my_memicmp(char *s1, char *s2, long len)
- {
- long pos=0;
- long result;
- while(pos < len) {
- result = tolower(s1[pos]) - tolower(s2[pos]);
- if(result)
- return result;
- pos++;
- }
- return 0;
- }
-